module vending_machine_mix1 (
        input clk, rst,              // 时钟与复位信号
        input [2:0] coin,            // 投币输入 (1元, 2元, 5元)
        input [2:0] sel,             // 商品选择输入

        //input goods_num_query;       // 库存查询信号

        output reg dispense,         // 商品输出信号
        output reg low_balance,      // 余额不足信号
        output reg [4:0] change,     // 找零输出
        output reg [4:0] balance     // 当前余额显示

    );

    // 状态定义
    reg [4:0] state, next_state; // 定义状态和下一个状态的寄存器，使用5位宽度
    reg [3:0] product_A_price, product_B_price, product_C_price; // 定义三个产品的价格寄存器，使用4位宽度
    reg [23:0] timer; // 计时器，用于返回IDLE状态

    // 初始化商品价格
    // initial begin
    //     product_A_price = 4; // 商品A的价格是4
    //     product_B_price = 6; // 商品B的价格是6
    //     product_C_price = 8; // 商品C的价格是8
    // end

    // 定义自动售货机的状态机状态

    //IDLE (0001)：空闲状态，等待输入。
    //COIN_IN (0010)：投币状态，接收用户的投币并记录余额。
    //DISPENSE (0100)：发放商品状态，商品成功发放后重置余额。
    //CHANGE (1000)：找零状态（此状态未实际用到，找零逻辑在 COIN_IN 中处理）。

    localparam IDLE = 5'b00001, COIN_IN = 5'b00010, SELECT = 5'b00100, DISPENSE = 5'b01000, CHANGE = 5'b10000;

    // // 状态转移逻辑
    // // 在时钟上升沿或复位上升沿触发状态转移
    // always @(posedge clk or posedge rst) begin
    //     if (rst)
    //         state <= IDLE; // 复位时，状态设置为IDLE
    //     else
    //         state <= next_state; // 否则，状态转移到next_state
    // end

    // 状态转移逻辑
    // 在时钟上升沿或复位上升沿触发状态转移
    always @(posedge clk or negedge rst) begin
        if (rst) begin
            state <= IDLE; // 复位时，状态设置为IDLE
            //timer <= 24'b0; // 计时器清零
        end
        else begin
            // if (state == COIN_IN || state == DISPENSE) begin
            //     if (coin == 3'b000) begin // 如果没有投币
            //         timer <= timer + 1; // 计时器加1
            //         if (timer == 24'hFFFFFF) // 如果计时器达到最大值（大约2秒）
            //             state <= IDLE; // 返回IDLE状态
            //     end
            //     else begin
            //         timer <= 24'b0; // 有投币时，计时器清零
            //         state <= next_state; // 否则，状态转移到next_state
            //     end
            // end
            // else begin
            state <= next_state; // 其他状态下，状态转移到next_state
            //end
        end
    end

    // 状态机：组合逻辑
    always @(*) begin
        // 根据当前状态和输入选择下一个状态，并设置输出信号
        case (state)

            IDLE: begin
                if (coin != 3'b000) // 如果有投币
                    next_state = COIN_IN; // 转入投币状态
                else
                    next_state = IDLE; // 否则保持空闲状态
            end

            COIN_IN: begin
                if (coin != 3'b000) // 如果有投币
                    next_state = COIN_IN; // 继续投币状态
                else
                    next_state = SELECT; // 否则转入选择状态
            end

            SELECT: begin
                if (sel != 3'b000 && low_balance >= 0) // 如果有选择商品
                    next_state = DISPENSE; // 转入发放商品状态
                else
                    next_state = change; // 否则转入找零(退钱)状态
            end

            DISPENSE: begin
                next_state = CHANGE; // 转入找零状态

            end

            CHANGE: begin
                next_state = IDLE; // 转入空闲状态
            end

            default: begin
                if (coin != 3'b000) // 如果有投币
                    next_state = COIN_IN; // 转入投币状态
                else
                    next_state = IDLE; // 否则保持空闲状态
            end

        endcase
    end



    always @(posedge clk or negedge reset) begin
        if (rst)
            dispense <= 0;
        low_balance <= 0;
        change <= 0;
        else
        case (next_state)
            IDLE: begin
                dispense <= 0;
                low_balance <= 0;
                balance <= 0;
                change <= 0;
            end
            COIN_IN: begin

                begin
                    if (rst)
                        balance <= 0;//复位时清零余额
                    else if (balance + (coin[0] * 1 + coin[1] * 2 + coin[2] * 5)>31) begin
                        //如果投币超出系统余额上限（最大余额为31元】
                        balance<=31;//设置余额为最大值
                    end
                    else begin
                        //根据投币金额更新余额
                        case (coin)
                            3'b001:
                                balance<=balance+1;//投入1元
                            3'b010:
                                balance<=balance+2;//投入2元
                            3'b100:
                                balance<=balance+5;//投入5元
                            default:
                                balance<=balance;//未投币时余额保持不变
                        endcase
                    end
                end

                // dispense <= 0;
                // low_balance <= 0;
                // change <= 0;
            end
            SELECT: begin

                begin
                    // 根据选择的商品判断是否可以购买，并计算找零
                    case (sel)
                        3'b001 = [15:0]16'd4;
                        3'b010 = [15:0]16'd6;
                        3'b100 = [15:0]16'd8;
                        default:
                            num[15:0]
                        endcase
                end
                if (balance >= num[15:0]) begin
                    change = balance - num[15:0];
                    loe_balance <= 0;
                end
                    else begin
                        change = balance;
                        low_balance <= 1;
                end

                // dispense <= 0;
                // low_balance <= 0;
                // balance <= 0;

            end
            DISPENSE: begin
                dispense <= 1;
                // low_balance <= 0;
                // balance <= 0;
                // change <= 0;
            end
            CHANGE: begin
                // dispense <= 0;
                // low_balance <= 0;
                // balance <= 0;
                change <= balance;
            end
            default: begin
                dispense <= 0;
                low_balance <= 0;
                balance <= 0;
                change <= 0;
            end
        endcase


    end


endmodule

